/*  yALB - Yet Another List Builder (roster Editor for Wargames/tabletop games).
    Copyright (C) 2008-2012  Daniel Ricardo Castro Alvarado

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/

#ifndef GAMESTRUCTS_H
#define GAMESTRUCTS_H

#include <QObject>
#include <QStringList>
#include <QVector>
#include <QSet>
#include <QSharedPointer>

#include "objectactions.h"

// \TODO: Change names of InheritedCategoryData and similar to better self-explaining names. Use them on the main classes.

typedef QVector<QSharedPointer<ObjectAction> > Actions;

class InheritedCategoryData {
public:
    uint numericLimit;
    uint pointLimit;
    uint percentageLimit;

    InheritedCategoryData () : numericLimit((uint)-1), pointLimit((uint)-1), percentageLimit((uint)-1) { }
};

class InheritedItemData {
public:
    float cost;
    int maxNumber;

    InheritedItemData() : cost(-1), maxNumber(-1) { }
};

class InheritedOptionData {
public:
    float cost;
    InheritedOptionData() : cost(0) { }
};

typedef QPair<QString, bool> KeyBoolPair;
typedef QPair<QString, QString> StringPair;
typedef QHash<QString, InheritedCategoryData> CategoryDataHash;

class GameCategory {
public:
    GameCategory();
    GameCategory(const QString &name, uint numericLimit, uint pointLimit,
                 uint percentageLimit);

    QString getName() const;
    uint getNumericLimit() const;
    uint getPointLimit() const;
    uint getPercentageLimit() const;

    void setName(const QString& name);
    void setNumericLimit(uint limit);
    void setPointLimit(uint limit);
    void setPercentageLimit(uint limit);

private:
    QString name;
    uint numericLimit;
    uint pointLimit;
    uint percentageLimit;
};

class Column {
public:
    QString defaultValue;
    QString defaultValueAs;
    bool visible;

    Column();
    Column(const QString& name, const QString& defaultValue,
           const QString& defaultValueAs, bool visible);

    QString getName() const;
    void setName(const QString& name);

private:
    QString name;
};

class GameProperty {
public:
    QString defaultValue;

    GameProperty();
    GameProperty(const QString& name, const QString& defaultValue);

    QString getName() const;
    void setName(const QString& name);

private:
    QString name;
};

class UnitOption {
public:
    enum InitialState {
        Normal = 0,
        EnabledLocked,
        EnabledInvisible,
        Locked,
        Invisible,
        ElementCount // For loops and conversions from int
    };
    InitialState state;
    QString category;
    QString required;
    bool costPerMin;
    Actions actions;
    QHash<QString, QString> properties;

#ifdef UNIT_OPTION_INHERITED_KEY
    QString inheritedKey;
#endif

    UnitOption();
    UnitOption(const QString& categoryKey, UnitOption::InitialState initialState,
               const QString& name, float cost, bool costPerMin, const QString& required,
               const Actions &actions,
               const QHash<QString, QString>& properties);

    QString getName() const;
    void setName(const QString& name);
    float getCost() const;
    void setCost(float newCost);

private:
    QString name;

    float cost;
};

class GameItem {
public:
    QString category;
    bool costPerMin;

    Actions actions;
    QHash<QString, QString> properties;

    GameItem();
    GameItem(const QString &categoryKey, const QString &name, float cost, bool costPerMin,
             uint maximumNumber, const Actions &actions,
             const QHash<QString, QString>& properties);

    QString getName() const;
    uint getMaximumNumber() const;
    void setName(const QString& name);
    void setMaximumNumber(uint maximumNumber);

    float getCost() const;
    void setCost(float newCost);

private:
    QString name;
    uint maximumNumber;

    float cost;
};

class GlobalText {
public:
    QString text;

    GlobalText();
    GlobalText(const QString& name, const QString& text);

    QString getName() const;
    void setName(const QString& name);

private:
    QString name;
};

class GameStructs : QObject {
public:
    static bool isValidKey(const QString& key);
    static UnitOption::InitialState getOptionStateFromInt(int initialState);
    static QVariant getActionListFromString(const QString &text);
    static QVariant getActionAddUnitData(const QString &text, bool replaceMin);
    static QVariant getActionCellData(const QString &key, const QString &value);
    static QString getValidName(const QString& name);
};

template <class T>
class KeyPair {
public:
    QString key;
    T value;

    KeyPair(const QString& key, const T& value) {
        this->key = key;
        this->value = value;
    }
    KeyPair() : key(), value() { }
};

class FileInformation {
public:
    QString name;
    QString creator;
    QString version;
    QString website;
    QString comments;

    FileInformation() { }
    FileInformation(const QString& _name, const QString& _creator,
                    const QString& _version, const QString& _website,
                    const QString& _comments) : name(_name), creator(_creator),
        version(_version), website(_website), comments(_comments) { }
};

// Inline functions

// Category struct

inline QString GameCategory::getName() const {
    return name;
}

inline uint GameCategory::getNumericLimit() const {
    return numericLimit;
}

inline uint GameCategory::getPointLimit() const {
    return pointLimit;
}

inline uint GameCategory::getPercentageLimit() const {
    return percentageLimit;
}

inline void GameCategory::setName(const QString &name) {
    this->name = GameStructs::getValidName(name);
}

inline void GameCategory::setNumericLimit(uint limit) {
    numericLimit = limit > 100 ? 100: limit;
}

inline void GameCategory::setPointLimit(uint limit) {
    pointLimit = limit;
}

inline void GameCategory::setPercentageLimit(uint limit) {
    percentageLimit = limit > 100 ? 100: limit;
}

// Column struct

inline QString Column::getName() const {
    return name;
}

inline void Column::setName(const QString &name) {
    this->name = GameStructs::getValidName(name);
}

// Property struct

inline QString GameProperty::getName() const {
    return name;
}

inline void GameProperty::setName(const QString &name) {
    this->name = GameStructs::getValidName(name);
}

// Option struct

inline QString UnitOption::getName() const {
    return name;
}

inline void UnitOption::setName(const QString &name) {
    this->name = GameStructs::getValidName(name);
}

inline void UnitOption::setCost(float newCost) {
    cost = (newCost <= 10000) ? (newCost >= 0 ? newCost : 0) : 10000;
}

inline float UnitOption::getCost() const {
    return cost;
}

// Item struct

inline QString GameItem::getName() const {
    return name;
}

inline uint GameItem::getMaximumNumber() const {
    return maximumNumber;
}

inline void GameItem::setName(const QString &name) {
    this->name = GameStructs::getValidName(name);
}

inline void GameItem::setMaximumNumber(uint maximumNumber) {
    this->maximumNumber = maximumNumber > 100 ? 100 : maximumNumber;
}

inline void GameItem::setCost(float newCost) {
    cost = (newCost <= 10000) ? (newCost >= 0 ? newCost : 0) : 10000;
}

inline float GameItem::getCost() const {
    return cost;
}

// Global text struct

inline QString GlobalText::getName() const {
    return name;
}

inline void GlobalText::setName(const QString &name) {
    this->name = GameStructs::getValidName(name);
}

#endif // GAMESTRUCTS_H
